﻿using MediatR;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.Reflection;
using System.Text;
using Traceability_2203.Common.DBContexts;
using Traceability_2203.Common.Infrastructure.Interfaces;
using Traceability_2203.Common.Infrastructure.Repositories;

namespace Traceability_2203.Bais.Api.Common
{
    /// <summary>
    /// 拓展方法 静态类+静态方法+this关键字
    /// </summary>
    public static class ExtensionServiceCollection
    {
        public static void AddService(this IServiceCollection services, IConfiguration configuration)
        {
            //注入ef上下文
            services.AddDBContext(configuration);

            services.AddControllers();
            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            services.AddEndpointsApiExplorer();
            services.AddSwaggerGen();

            //注册中介者模式 //获取当前执行代码所在的程序集(assembly)信息的一个方法
            services.AddMediatR(Assembly.GetExecutingAssembly());

            //依赖注入
            services.AddScoped(typeof(IBaseRepository<>), typeof(BaseRepository<>));

            services.AddHttpContextAccessor();
            services.AddScoped<IIdentityService, IdentityService>();

            //注册AutoMapper
            //如果你只有一个映射配置类,可以像这样直接注册它
            services.AddAutoMapper(typeof(AutoMapperProfile));
            //或者,如果你有多个映射配置类并且它们都在同一个命名空间中,可以这样注册
            //注意:这将会加载指定命名空间下的所有profile类
            //builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());


            //读取配置文件里的jwt配置
            var jwtSettings = configuration.GetSection("JWT").Get<JwtSettings>();
            //添加认证
            //// 设置默认的身份验证为 JwtBearer
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            // 配置 JWT Bearer 选项
            .AddJwtBearer(options =>
            {
                // 配置 Token 验证参数
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    //过期时间容错值，解决服务器端时间不同步问题（秒）
                    //允许服务器时间偏移量30秒，即我们配置的过期时间加上这个允许偏移的时间值，才是真正过期的时间(过期时间 + 偏移值)你也可以设置为0，ClockSkew = TimeSpan.Zero
                    ClockSkew = TimeSpan.FromSeconds(30),
                    ValidateIssuer = true,// 验证发行者 
                    ValidateAudience = true, // 验证受众
                    ValidateLifetime = true, // 验证令牌有效期
                    ValidateIssuerSigningKey = true,// 验证签名密钥
                    ValidIssuer = jwtSettings.Issuer,// 发行者
                    ValidAudience = jwtSettings.Audience,// 受众
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecurityKey))// 签名密钥
                };
            });

            // 配置Swagger
            services.AddSwaggerGen(o =>
            {
                var path = AppDomain.CurrentDomain.BaseDirectory + "Traceability_2203.Bais.Api.Xml";
                o.IncludeXmlComments(path, true);
                // 显示 授权信息
                o.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme()
                {
                    Description = "添加JWT授权Token：Bearer Token值",
                    Name = "Authorization",
                    In = Microsoft.OpenApi.Models.ParameterLocation.Header,
                    Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey,
                    BearerFormat = "JWT",
                    Scheme = "Bearer"
                });
                o.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        },
                        new string[]
                        {

                        }
                    }
                });
            });
        }

        public static void AddDBContext(this IServiceCollection services, IConfiguration configuration)
        {
            //注入ef上下文
            services.AddDbContext<EFDBContext>(x =>
            {
                x.UseSqlServer(configuration.GetConnectionString("Conn"));
            });
        }
    }
}
